#ifndef SOCKET
#define SOCKET

#include "Common.h"
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>

const int MAX_BACKLOG_SIZE = 1024;
const int BufferSize = 1024;

constexpr ssize_t SOCKET_EAGAIN = -2; // non-blocking operation would block marker

class Socket
{
public:
    Socket();
    Socket(int fd);
    ~Socket();

    int getFd();

    bool CreateSocket();
    bool BindAddress(const std::string &addr, uint16_t port);
    bool Listen(int backlog = MAX_BACKLOG_SIZE);
    bool ConnServer(const std::string &addr, uint16_t port);
    int Accept();
    ssize_t Recv(void *buf, size_t len, int flag = 0);
    ssize_t NonBlockRecv(void *buf, size_t len);
    ssize_t Send(const void *buf, size_t len, int flag = 0);
    ssize_t NonBlockSend(void *buf, size_t len);
    void Close();

    bool CreateServerConn(uint16_t port, const std::string &addr = "0.0.0.0");
    bool CreateClientConn(uint16_t port, const std::string &addr);

    void ReuseAddress();
    void NonBlock();
    void SetTcpNoDelay();
    void SetKeepAlive();

private:
    int _fd;
};

#endif
